﻿namespace _7_方法;

internal enum QQStatus
{
    Online,
    Offline,
    Busy,
    QingGuan
}

internal class Base
{
    public void PrintInfo()
    {
        Console.WriteLine("我是Base类中的打印语句");
    }
}

internal class Derived : Base
{
    public new void PrintInfo() // new 关键字表示隐藏父类中相同名字的该方法
    {
        base.PrintInfo(); // 使用base关键字调用父类中定义的方法
        Console.WriteLine("我是Derived类中的打印语句");
    }
}

internal class BaseClass
{
    // 见名知意: 就是一个虚拟方法, 可以在子类中重新定义该虚拟方法
    public virtual void PrintInfo()
    {
        Console.WriteLine("我是BaseClass中的打印语句");
    }
}

internal class DerivedClass : BaseClass
{
    // override: 重新定义父类中定义的该方法
    // 如果存在override, 则子类的对象将会调用这个重写之后的方法, 而不是调用父类中定义的方法
    public override void PrintInfo()
    {
        base.PrintInfo(); // 当然此处也可调用父类中定义的方法
        Console.WriteLine("我是DerivedClass中的打印语句");
    }
}

internal class BaseClassSeale
{
    public virtual void PrintInfo()
    {
        Console.WriteLine("我是BaseClassSeale中的打印语句");
    }
}

internal class DerivedClassSeale : BaseClassSeale
{
    // sealed: 密封方法, 密封类
    public sealed override void PrintInfo()
    {
        Console.WriteLine("我是DerivedClassSeale中的打印语句");
    }
}

internal class User
{
    public string Name { get; set; }

    public string Occupation { get; set; }

    // 这个就是那个表达式主体定义, 好像这个lambda表达式啊
    public override string ToString()
    {
        return $"{Name} is a {Occupation}";
    }
}

internal sealed class MyOwnClass : BaseClassSeale
{
    public override void PrintInfo()
    {
        base.PrintInfo();
        Console.WriteLine("我是MyOwnClass中的打印语句");
    }
}

internal class threeDaiDerivedClassSeale : DerivedClassSeale
{
    // 此处如果重写的话则无法使用, 会报错, 因为该方法是被密封的, 是被sealed修饰的
    //public override void PrintInfo()
    //{
    //    base.PrintInfo();
    //    Console.WriteLine("我是threeDaiDerivedClassSeale中的打印语句");
    //}
}

internal class Test
{
    private readonly int x = 1;

    public void Test1()
    {
        var x = 2;
        Console.WriteLine($"我是Test1方法中定义的x: {x}"); // 2
        Console.WriteLine($"我是Test类中定义的x: {this.x}"); // 1
    }
}

internal class Program
{
    private static void Main(string[] args)
    {
        #region 1_方法定义

        // 1. 减少代码重复
        // 2. 复杂问题简单化
        // 3. 提高代码清晰度
        // 4. 重用代码
        // 5. 信息隐藏

        #endregion

        #region 2_变量数量可变params

        //Sum(1, 2, 3);
        //Sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        #endregion

        #region 3_返回元组

        //(QQStatus status1, QQStatus status2, QQStatus status3) = GetAllStatus();
        //Console.WriteLine(status1);
        //Console.WriteLine(status2);
        //Console.WriteLine(status3);

        #endregion

        #region 4_匿名方法(个人感觉使用的很少, 如果有必要, 就使用lambda表达式)

        //var timer = new System.Timers.Timer();
        //// 每隔一秒触发一次
        //// 匿名方法可以使用lambda表达式代替
        ////timer.Elapsed += new System.Timers.ElapsedEventHandler()
        //timer.Elapsed += (sender, e) =>
        //{
        //    Console.WriteLine("Timer is ticking");
        //};
        //timer.Interval = 1000;
        //timer.Enabled = true;
        //Console.ReadKey();

        #endregion

        #region 5_通过值, 通过引用传递参数(Swap方法重载)

        //int a = 1;
        //int b = 2;
        //// 1_普通值传递, 不改变原始参数的值
        //Swap(a, b);
        //// 2_引用传递, 改变原始参数的值
        //Swap(ref a, ref b);
        //int c;
        //var d = 4;
        //// 3_通过out关键字, 改变原始参数的值, 原始参数可以 不用声明和赋值
        //SwapOut(out c, out d);
        //Console.WriteLine(c);
        //Console.WriteLine(d);
        //Console.WriteLine(a); // 1 2
        //Console.WriteLine(b); // 2 1

        #endregion

        #region 6_递归: 条件调用函数自身

        //int x = Fibonacci(12);
        //Console.WriteLine(x);

        #endregion

        #region 7_方法作用域

        //var test = new Test();
        //test.Test1();

        #endregion

        #region 8_隐藏方法 new

        //var derived = new Derived();
        //derived.PrintInfo();

        #endregion

        #region 9_覆盖方法 virtual override

        //var baseClass = new BaseClass();
        //baseClass.PrintInfo();
        //var derivedClass = new DerivedClass();
        //derivedClass.PrintInfo();

        #endregion

        #region 10_隐藏方法和覆盖方法的区别

        #endregion

        #region 11_本地函数

        //PrintMessage("hello world");
        //// 在函数中定义的方法被称为本地函数,  递归就是一种本地函数(特例)
        //void PrintMessage(string message)
        //{
        //    Console.WriteLine($"{message}");
        //}

        #endregion

        #region 12_密封方法 sealed

        // 1_密封方法, 密封类
        // 如果不希望类被继承或者方法被继承使用, 可以使用sealed修饰符
        // 详见于threeDaiDerivedClassSeale

        #endregion

        #region 13_方法的表达式主体定义

        // 详见于User类
        var user = new User();
        user.Name = "Tom";
        user.Occupation = "Programmer";
        Console.WriteLine(user.ToString());

        #endregion
    }

    private static void Sum(params int[] list)
    {
        Console.WriteLine($"There are {list.Count()} items");
        var sum = 0;
        foreach (var item in list) sum += item;
        Console.WriteLine($"Sum is {sum}");
    }

    private static (QQStatus, QQStatus, QQStatus) GetAllStatus()
    {
        return (QQStatus.Busy, QQStatus.Offline, QQStatus.Online);
    }


    private static void Swap(int a, int b)
    {
        var temp = a;
        a = b;
        b = temp;
    }

    private static void Swap(ref int a, ref int b)
    {
        var temp = a;
        a = b;
        b = temp;
    }

    private static void SwapOut(out int a, out int b)
    {
        a = 1;
        b = 2;
    }

    private static int Fibonacci(int n)
    {
        if (n <= 1)
            return n;
        return Fibonacci(n - 1) + Fibonacci(n - 2);
    }
}